#pragma once
#include <vector>
#include <string>
#include "../comm/util.h"
#include "../comm/msg.pb.h"

using namespace std;

namespace ns_route
{
    class Router
    {
    public:
        static bool is_legal_routingkey(const string &routing_key)
        {
            // 规则：(a~z A~Z 0~9 . _)
            for (auto &ch : routing_key)
            {
                if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
                    (ch >= '0' && ch <= '9') || (ch == '.' || ch == '_'))
                    continue;
                else
                    return false;
            }
            return true;
        }

        static bool is_legal_bindingkey(const string &binding_key)
        {
            // 规则：(a~z A~Z 0~9 . _ * #) #：匹配零个或多个单词 *：匹配一个单词
            // # *两边不能有字母，且#两边不能有* #
            for (auto &ch : binding_key)
            {
                if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
                    (ch >= '0' && ch <= '9') || (ch == '.' || ch == '_') ||
                    (ch == '*' || ch == '#'))
                    continue;
                else
                    return false;
            }

            vector<string> vs;
            ns_util::StrSplit::Split(binding_key, ".", vs);
            // # *两边不能有字母
            for (auto &str : vs)
            {
                if (str.size() > 1 &&
                    (str.find('*') != string::npos || str.find('#') != string::npos))
                    return false;
            }
            // #两边不能有*
            for (int i = 1; i < vs.size(); i++)
            {
                if ((vs[i] == "#" && vs[i - 1] == "*") ||
                    (vs[i] == "*" && vs[i - 1] == "#") || (vs[i] == "#" && vs[i - 1] == "#"))
                    return false;
            }

            return true;
        }

        static bool route(ns_proto::ExchangeType type, const string &routing_key,
                          const string &bidning_key)
        {
            // 广播交换 直接交换 主题交换
            if (type == ns_proto::FANOUT)
                return true;
            if (type == ns_proto::DIRECT && routing_key == bidning_key)
                return true;
            if (type == ns_proto::TOPIC && str_match(routing_key, bidning_key))
            {
                return true;
            }

            return false;
        }

    private:
        static bool str_match(const string &routing_key, const string binding_key)
        {
            vector<string> rstr, bstr;
            int rks = ns_util::StrSplit::Split(routing_key, ".", rstr);
            int bks = ns_util::StrSplit::Split(binding_key, ".", bstr);

            // 创建二维数组表示当前两字符串的[i,j]之前的位置是否匹配
            vector<vector<bool>> dp(bks + 1, vector<bool>(rks + 1, false));
            dp[0][0] = true;

            // 当#位于起始位置时且匹配0个字母的情况
            if (bstr[0] == "#")
                dp[1][0] = true;
            for (int i = 0; i < bks; i++)
            {
                for (int j = 0; j < rks; j++)
                {
                    if (bstr[i] == rstr[j] || bstr[i] == "*")
                    {
                        dp[i + 1][j + 1] = dp[i][j];
                    }
                    else if (bstr[i] == "#") // 存在配0个、1个、多个单词的情况
                    {
                        dp[i + 1][j + 1] = (dp[i][j] ||     // 匹配一个字符
                                            dp[i + 1][j] || // 连续匹配多个字母
                                            dp[i][j + 1]);  // 位于中间、结尾且匹配0个字母
                    }
                }
            }
            return dp[bks][rks];
        }
    };
}